
#include <stl/set.h>
#include <stl/vector.h>
#include <standard/geometrymath.h>
#include <standard/notification.h>
#include "operator/terrainblockheightoperator.h"
#include "helper/terrainactiveblockhelperobject.h"
#include "editorscenemgr.h"
#include "scene/editorscene.h"
#include "terrain/terrainblock.h"
#include "terrain/terrainobject.h"
#include "ui/terrainpanel.h"
#include "command/terrainheightdatacmd.h"
#include "command/commandmgr.h"
#include "global.h"





CTerrainHeightOperator::CTerrainHeightOperator( CEditorSceneMgr* pSceneMgr ):
COperator( pSceneMgr ) {
    m_eOperatorType = EOT_COUNT;
    m_bIsButtonDown = False;
    m_nButtonDownX = 0;
    m_nButtonDownY = 0;

    m_nButtonWorkX = 0;
    m_nButtonWorkY = 0;
}
CTerrainHeightOperator::~CTerrainHeightOperator(){

}
bool32 CTerrainHeightOperator::Init(){
    int32 _nBrushType = CTerrainPanel::GetInterface()->GetSelectTerrainBrushType();
    int32 _nBrushSize = CTerrainPanel::GetInterface()->GetSelectTerrainBrushSize();
    m_rTerrainActiveBlockHelperObject = NEW CTerrainActiveBlockHelperObject();
    m_rTerrainActiveBlockHelperObject->Init( m_pSceneMgr->GetTerrainObject(), _nBrushType, _nBrushSize);
    m_pSceneMgr->GetScene()->AddChild(m_rTerrainActiveBlockHelperObject.GetEntityData());
    m_pSceneMgr->SetSceneVisibleMode( 0 );
    NOTIFICATION_REGISTER(SETTERRAINBRUSHTYPENOTIFICATION, 0, this, CTerrainHeightOperator::OnNotification_SetTerrainBrushType);
    return True;
}
bool32 CTerrainHeightOperator::Final(){
    m_pSceneMgr->GetScene()->RemoveChild(m_rTerrainActiveBlockHelperObject.GetEntityData());
    m_rTerrainActiveBlockHelperObject.Detach();
    NOTIFICATION_REMOVE_DELEGATE(SETTERRAINBRUSHTYPENOTIFICATION, this, CTerrainHeightOperator::OnNotification_SetTerrainBrushType);
    return True;
}
bool32 CTerrainHeightOperator::OnLMouseDown( int32 x, int32 y ){
    STerrainSelectedPosInfo _sTerrainSelectedPosInfo;
    CTerrainBlock* _pTerrainBlock = m_pSceneMgr->GetSelectBlock(x, y, &_sTerrainSelectedPosInfo );
    if (_pTerrainBlock) {
        SSETSTATUSCOORDTEXT _sSETSTATUSCOORDTEXT;
        _sSETSTATUSCOORDTEXT.m_fPosX = _sTerrainSelectedPosInfo.m_vPos[0];
        _sSETSTATUSCOORDTEXT.m_fPosY = _sTerrainSelectedPosInfo.m_vPos[1];
        _sSETSTATUSCOORDTEXT.m_fPosZ = _sTerrainSelectedPosInfo.m_vPos[2];
        _sSETSTATUSCOORDTEXT.m_nCellX = _sTerrainSelectedPosInfo.m_nCellX;
        _sSETSTATUSCOORDTEXT.m_nCellY = _sTerrainSelectedPosInfo.m_nCellY;

        NOTIFICATION_SEND(SETSTATUSCOORDTEXT, 0, 0, &_sSETSTATUSCOORDTEXT);
        int32 _nBrushSize = CTerrainPanel::GetInterface()->GetSelectTerrainBrushSize();
        //int32 _nSelectTerrainHeightType = CTerrainPanel::GetInterface()->GetSelectTerrainHeightType();
        list<CTerrainBlock*>* _pvTerrainBlockList = m_rTerrainActiveBlockHelperObject->UpdateActiveBlock( _sTerrainSelectedPosInfo.m_nCellX, _sTerrainSelectedPosInfo.m_nCellY, _nBrushSize);
        m_bIsButtonDown = True;
        m_nButtonWorkX = x;
        m_nButtonWorkY = y;
        m_nButtonDownX = x;
        m_nButtonDownY = y;

        m_vTerrainCellHeightInfoList.clear();
        return True;
    }
    return False;
}
bool32 CTerrainHeightOperator::OnMouseMove( int32 x, int32 y ){
    STerrainSelectedPosInfo _sTerrainSelectedPosInfo;
    CTerrainBlock* _pTerrainBlock = m_pSceneMgr->GetSelectBlock(x, y, &_sTerrainSelectedPosInfo );
    if (_pTerrainBlock) {
        SSETSTATUSCOORDTEXT _sSETSTATUSCOORDTEXT;
        _sSETSTATUSCOORDTEXT.m_fPosX = _sTerrainSelectedPosInfo.m_vPos[0];
        _sSETSTATUSCOORDTEXT.m_fPosY = _sTerrainSelectedPosInfo.m_vPos[1];
        _sSETSTATUSCOORDTEXT.m_fPosZ = _sTerrainSelectedPosInfo.m_vPos[2];
        _sSETSTATUSCOORDTEXT.m_nCellX = _sTerrainSelectedPosInfo.m_nCellX;
        _sSETSTATUSCOORDTEXT.m_nCellY = _sTerrainSelectedPosInfo.m_nCellY;
        NOTIFICATION_SEND(SETSTATUSCOORDTEXT, 0, 0, &_sSETSTATUSCOORDTEXT );
        int32 _nBrushSize = CTerrainPanel::GetInterface()->GetSelectTerrainBrushSize();
        list<CTerrainBlock*>* _pvTerrainBlockList = m_rTerrainActiveBlockHelperObject->UpdateActiveBlock( _sTerrainSelectedPosInfo.m_nCellX, _sTerrainSelectedPosInfo.m_nCellY, _nBrushSize);
        if (m_bIsButtonDown) {
            if (m_nButtonWorkX != x || m_nButtonWorkY != y) {
                _Work(_sTerrainSelectedPosInfo.m_nCellX, _sTerrainSelectedPosInfo.m_nCellY, _nBrushSize);
                m_nButtonWorkX = x;
                m_nButtonWorkY = y;
                return True;
            }
        }
    }
    return False;
}
bool32 CTerrainHeightOperator::OnLMouseUp( int32 x, int32 y ){
    bool32 _bResult = False;
    if (m_bIsButtonDown) {
        if (m_nButtonDownX == x || m_nButtonDownY == y) {
            STerrainSelectedPosInfo _sTerrainSelectedPosInfo;
            CTerrainBlock* _pTerrainBlock = m_pSceneMgr->GetSelectBlock(x, y, &_sTerrainSelectedPosInfo);
            if (_pTerrainBlock) {
                int32 _nBrushSize = CTerrainPanel::GetInterface()->GetSelectTerrainBrushSize();
                _Work(_sTerrainSelectedPosInfo.m_nCellX, _sTerrainSelectedPosInfo.m_nCellY, _nBrushSize);
                _bResult = True;
            }
        }

        _FinishedWork();
    }
    m_bIsButtonDown = False;
    m_nButtonDownX = 0;
    m_nButtonDownY = 0;

    m_nButtonWorkX = 0;
    m_nButtonWorkY = 0;
    return _bResult;
}
void CTerrainHeightOperator::OnNotification_SetTerrainBrushType( int32 w, int32 l, void* pUserData ){
    m_rTerrainActiveBlockHelperObject->SetBrushInfo(w, l);
}
void CTerrainHeightOperator::_AddTerrainCellHeightInfo( int32 x, int32 y, float fValue ){
    uint32 _nKey = MAKELONG( y, x );
    if(m_vTerrainCellHeightInfoList.find( _nKey ) == m_vTerrainCellHeightInfoList.end()){
        m_vTerrainCellHeightInfoList.insert( _nKey, fValue );
    }
}
void CTerrainHeightOperator::_FinishedWork(){
    CTerrainHeightCmd* _pTerrainHeightCmd = NEW CTerrainHeightCmd( &m_vTerrainCellHeightInfoList );
    m_pSceneMgr->GetCommandMgr()->AddCommand( _pTerrainHeightCmd );
    m_vTerrainCellHeightInfoList.clear();
}
    

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CTerrainHeightRiseOperator::CTerrainHeightRiseOperator(CEditorSceneMgr* pSceneMgr):
CTerrainHeightOperator( pSceneMgr ) {
    m_eOperatorType = EOT_TERRAIN_HEIGHT_RISE_EDIT;
}
CTerrainHeightRiseOperator::~CTerrainHeightRiseOperator() {

}
float CTerrainHeightRiseOperator::_RiseCurve(float x) {
    return (0.5f * (sin(PI * x - (PI * 0.5f)) + 1));
}
void CTerrainHeightRiseOperator::_Work( int32 nCellX, int32 nCellY, int32 nBrushSize) {
    const float _fRiseHeight = 10.0f;
    int32 _nCoordX = nCellX;
    int32 _nCoordY = nCellY;
    int32 _nHalfBrushSize = nBrushSize / 2;
    set<CTerrainBlock*> _vTerrainBlockList;

    CTerrainBlock* _vTerrainBlock[4];
    CTerrainObject* _pTerrainObject = m_pSceneMgr->GetTerrainObject();
    if (_nHalfBrushSize > 0) {
        float _fMaxDistance = sqrt(Distance(_nCoordX, _nCoordY, _nCoordX + _nHalfBrushSize, _nCoordY + _nHalfBrushSize));
        for (int32 j = _nCoordY - _nHalfBrushSize; j <= _nCoordY + _nHalfBrushSize; j++) {
            for (int32 i = _nCoordX - _nHalfBrushSize; i <= _nCoordX + _nHalfBrushSize; i++) {
                if(i < 0 || j < 0 || i >= _pTerrainObject->m_nCellCountX || j >= _pTerrainObject->m_nCellCountY)
                    continue;
                
                int32 _nTerrainBlock = _pTerrainObject->GetCellBlock( i, j, _vTerrainBlock );
                for( int32 n = 0; n < _nTerrainBlock; n ++ ){
                    _vTerrainBlockList.insert( _vTerrainBlock[n] );
                }

                float _fHeight = _pTerrainObject->GetCellHeight( i, j );
                float _fDistence = sqrt(Distance<float>( _nCoordX, _nCoordY, i, j ));
                float _fAlpha = (_fMaxDistance - _fDistence) / _fMaxDistance;
                float _fDelta = _RiseCurve(_fAlpha);
                if(_fDelta > 0.0f){
                    _AddTerrainCellHeightInfo( i, j, _fHeight );
                    _fHeight += _fDelta * _fRiseHeight;
                    _pTerrainObject->SetCellHeight( i, j, _fHeight );
                }
            }
        }
    }else {
        int32 _nTerrainBlock = _pTerrainObject->GetCellBlock( _nCoordX, _nCoordY, _vTerrainBlock );
        for( int32 n = 0; n < _nTerrainBlock; n ++ ){
            _vTerrainBlockList.insert( _vTerrainBlock[n] );
        }

        float _fHeight = _pTerrainObject->GetCellHeight( _nCoordX, _nCoordY );
        _AddTerrainCellHeightInfo( _nCoordX, _nCoordY, _fHeight );
        _fHeight += _fRiseHeight;
        _pTerrainObject->SetCellHeight( _nCoordX, _nCoordY, _fHeight );
    }
    set< CTerrainBlock* >::iterator it = _vTerrainBlockList.begin();
    set< CTerrainBlock* >::iterator it_end = _vTerrainBlockList.end();
    for (; it != it_end; it++) {
        CTerrainBlock* _pTerrainBlock = it.first();
        _pTerrainBlock->UpdateGeometry();
    }
    m_rTerrainActiveBlockHelperObject->UpdateActiveBlock( _nCoordX, _nCoordY, nBrushSize, True );
}



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CTerrainHeightFallOperator::CTerrainHeightFallOperator( CEditorSceneMgr* pSceneMgr ):
CTerrainHeightOperator( pSceneMgr ){
    m_eOperatorType = EOT_TERRAIN_HEIGHT_FALL_EDIT;
}
CTerrainHeightFallOperator::~CTerrainHeightFallOperator(){

}
void CTerrainHeightFallOperator::_Work( int32 nCellX, int32 nCellY, int32 nBrushSize ){
    const float _fRiseHeight = 10.0f;
    int32 _nCoordX = nCellX;
    int32 _nCoordY = nCellY;
    int32 _nHalfBrushSize = nBrushSize / 2;
    set<CTerrainBlock*> _vTerrainBlockList;
    CTerrainBlock* _vTerrainBlock[4];

    CTerrainObject* _pTerrainObject = m_pSceneMgr->GetTerrainObject();
    if (_nHalfBrushSize > 0) {
        float _fMaxDistance = sqrt(Distance(_nCoordX, _nCoordY, _nCoordX + _nHalfBrushSize, _nCoordY + _nHalfBrushSize));
        for (int32 j = _nCoordY - _nHalfBrushSize; j <= _nCoordY + _nHalfBrushSize; j++) {
            for (int32 i = _nCoordX - _nHalfBrushSize; i <= _nCoordX + _nHalfBrushSize; i++) {
                if(i < 0 || j < 0 || i >= _pTerrainObject->m_nCellCountX || j >= _pTerrainObject->m_nCellCountY)
                    continue;
                
                int32 _nTerrainBlock = _pTerrainObject->GetCellBlock( i, j, _vTerrainBlock );
                for( int32 n = 0; n < _nTerrainBlock; n ++ ){
                    _vTerrainBlockList.insert( _vTerrainBlock[n] );
                }
                float _fHeight = _pTerrainObject->GetCellHeight( i, j );
                float _fDistence = sqrt(Distance<float>( _nCoordX, _nCoordY, i, j ));
                float _fAlpha = (_fMaxDistance - _fDistence) / _fMaxDistance;
                float _fDelta = _FallCurve(_fAlpha);
                if(_fDelta > 0.0f){
                    _AddTerrainCellHeightInfo( i, j, _fHeight );
                    _fHeight -= _fDelta * _fRiseHeight;
                    _pTerrainObject->SetCellHeight( i, j, _fHeight );
                }
            }
        }
    }else {
        int32 _nTerrainBlock = _pTerrainObject->GetCellBlock( _nCoordX, _nCoordY, _vTerrainBlock );
        for( int32 n = 0; n < _nTerrainBlock; n ++ ){
            _vTerrainBlockList.insert( _vTerrainBlock[n] );
        }
        float _fHeight = _pTerrainObject->GetCellHeight( _nCoordX, _nCoordY );
        _AddTerrainCellHeightInfo( _nCoordX, _nCoordY, _fHeight );
        _fHeight -= _fRiseHeight;
        _pTerrainObject->SetCellHeight( _nCoordX, _nCoordY, _fHeight );
    }
    set< CTerrainBlock* >::iterator it = _vTerrainBlockList.begin();
    set< CTerrainBlock* >::iterator it_end = _vTerrainBlockList.end();
    for (; it != it_end; it++) {
        CTerrainBlock* _pTerrainBlock = it.first();
        _pTerrainBlock->UpdateGeometry();
    }
    m_rTerrainActiveBlockHelperObject->UpdateActiveBlock( _nCoordX, _nCoordY, nBrushSize, True );

}
float CTerrainHeightFallOperator::_FallCurve( float x ){
    return (0.5f * (sin(PI * x - (PI * 0.5f)) + 1));
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CTerrainHeightFlatOperator::CTerrainHeightFlatOperator( CEditorSceneMgr* pSceneMgr ):
CTerrainHeightOperator( pSceneMgr ){
    m_eOperatorType = EOT_TERRAIN_HEIGHT_FLAT_EDIT;
}
CTerrainHeightFlatOperator::~CTerrainHeightFlatOperator(){

}
void CTerrainHeightFlatOperator::_Work( int32 nCellX, int32 nCellY, int32 nBrushSize ){
    int32 _nCoordX = nCellX;
    int32 _nCoordY = nCellY;
    int32 _nHalfBrushSize = nBrushSize / 2;
    set<CTerrainBlock*> _vTerrainBlockList;
    CTerrainBlock* _vTerrainBlock[4];

    CTerrainObject* _pTerrainObject = m_pSceneMgr->GetTerrainObject();
    if (_nHalfBrushSize > 0) {
        float _fAllHeight = 0.0f;
        float _fCellCount = 0;
        float _fMaxDistance = sqrt(Distance(_nCoordX, _nCoordY, _nCoordX + _nHalfBrushSize, _nCoordY + _nHalfBrushSize));
        for (int32 j = _nCoordY - _nHalfBrushSize; j <= _nCoordY + _nHalfBrushSize; j++) {
            for (int32 i = _nCoordX - _nHalfBrushSize; i <= _nCoordX + _nHalfBrushSize; i++) {
                if(i < 0 || j < 0 || i >= _pTerrainObject->m_nCellCountX || j >= _pTerrainObject->m_nCellCountY)
                    continue;
                int32 _nTerrainBlock = _pTerrainObject->GetCellBlock( i, j, _vTerrainBlock );
                for( int32 n = 0; n < _nTerrainBlock; n ++ ){
                    _vTerrainBlockList.insert( _vTerrainBlock[n] );
                }
                float _fHeight = _pTerrainObject->GetCellHeight( i, j );
                _fAllHeight += _fHeight;
                _fCellCount++;
            }
        }

        _fAllHeight /= _fCellCount;
        for (int32 j = _nCoordY - _nHalfBrushSize; j <= _nCoordY + _nHalfBrushSize; j++) {
            for (int32 i = _nCoordX - _nHalfBrushSize; i <= _nCoordX + _nHalfBrushSize; i++) {
                if(i < 0 || j < 0 || i >= _pTerrainObject->m_nCellCountX || j >= _pTerrainObject->m_nCellCountY)
                    continue;
                float _fHeight = _pTerrainObject->GetCellHeight( i, j );
                _AddTerrainCellHeightInfo( i, j, _fHeight );
                _pTerrainObject->SetCellHeight( i, j, _fAllHeight );
            }
        }
        set< CTerrainBlock* >::iterator it = _vTerrainBlockList.begin();
        set< CTerrainBlock* >::iterator it_end = _vTerrainBlockList.end();
        for (; it != it_end; it++) {
            CTerrainBlock* _pTerrainBlock = it.first();
            _pTerrainBlock->UpdateGeometry();
        }
        m_rTerrainActiveBlockHelperObject->UpdateActiveBlock( _nCoordX, _nCoordY, nBrushSize, True );
    }else {
        //CTerrainBlock* _pTerrainBlock = _pTerrainObject->GetCellBlock( _nCoordX, _nCoordY );
        //_vTerrainBlockList.insert( _pTerrainBlock );
        //float _fHeight = _pTerrainObject->GetCellHeight( _nCoordX, _nCoordY );
        //_fHeight += _fRiseHeight;
        //_pTerrainObject->SetCellHeight( _nCoordX, _nCoordY, _fHeight );
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CTerrainHeightSteepOperator::CTerrainHeightSteepOperator( CEditorSceneMgr* pSceneMgr ):
CTerrainHeightOperator( pSceneMgr ){
    m_eOperatorType = EOT_TERRAIN_HEIGHT_STEEP_EDIT;
}
CTerrainHeightSteepOperator::~CTerrainHeightSteepOperator(){

}
float CTerrainHeightSteepOperator::_SteepCurve(float x, float y) {
    //return sin(4*x) + cos(4*y);
    float _fPeriod = 1.5f;
    return sin(_fPeriod *(x + y)) + cos(_fPeriod *(x - y));
}
void CTerrainHeightSteepOperator::_Work( int32 nCellX, int32 nCellY, int32 nBrushSize ){
    const float _fRiseHeight = 64.0f;
    int32 _nCoordX = nCellX;
    int32 _nCoordY = nCellY;
    int32 _nHalfBrushSize = nBrushSize / 2;
    set<CTerrainBlock*> _vTerrainBlockList;
    CTerrainBlock* _vTerrainBlock[4];
    float _fLineX = 0.023f;
    float _fLineY = 0.017f;

    CTerrainObject* _pTerrainObject = m_pSceneMgr->GetTerrainObject();
    if (_nHalfBrushSize > 0) {
        float _fMaxDistance = sqrt(Distance(_nCoordX, _nCoordY, _nCoordX + _nHalfBrushSize, _nCoordY + _nHalfBrushSize));
        for (int32 j = _nCoordY - _nHalfBrushSize; j <= _nCoordY + _nHalfBrushSize; j++) {
            for (int32 i = _nCoordX - _nHalfBrushSize; i <= _nCoordX + _nHalfBrushSize; i++) {
                if(i < 0 || j < 0 || i >= _pTerrainObject->m_nCellCountX || j >= _pTerrainObject->m_nCellCountY)
                    continue;
                
                int32 _nTerrainBlock = _pTerrainObject->GetCellBlock( i, j, _vTerrainBlock );
                for( int32 n = 0; n < _nTerrainBlock; n ++ ){
                    _vTerrainBlockList.insert( _vTerrainBlock[n] );
                }

                float _fHeight = _pTerrainObject->GetCellHeight( i, j );
                _AddTerrainCellHeightInfo( i, j, _fHeight );
                float _fDelta = _SteepCurve( i + _fLineX, j + _fLineY);
                _fHeight = _fDelta * _fRiseHeight;
                _pTerrainObject->SetCellHeight( i, j, _fHeight );
            }
        }
    }else {
        int32 _nTerrainBlock = _pTerrainObject->GetCellBlock( _nCoordX, _nCoordY, _vTerrainBlock );
        for( int32 n = 0; n < _nTerrainBlock; n ++ ){
            _vTerrainBlockList.insert( _vTerrainBlock[n] );
        }

        float _fHeight = _pTerrainObject->GetCellHeight( _nCoordX, _nCoordY );
        _fHeight += _fRiseHeight;
        _pTerrainObject->SetCellHeight( _nCoordX, _nCoordY, _fHeight );
    }
    set< CTerrainBlock* >::iterator it = _vTerrainBlockList.begin();
    set< CTerrainBlock* >::iterator it_end = _vTerrainBlockList.end();
    for (; it != it_end; it++) {
        CTerrainBlock* _pTerrainBlock = it.first();
        _pTerrainBlock->UpdateGeometry();
    }
    m_rTerrainActiveBlockHelperObject->UpdateActiveBlock( _nCoordX, _nCoordY, nBrushSize, True );

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CTerrainHeightSmoothOperator::CTerrainHeightSmoothOperator( CEditorSceneMgr* pSceneMgr ):
CTerrainHeightOperator( pSceneMgr ){
    m_eOperatorType = EOT_TERRAIN_HEIGHT_SMOOTH_EDIT;
}
CTerrainHeightSmoothOperator::~CTerrainHeightSmoothOperator(){

}
void CTerrainHeightSmoothOperator::_Work( int32 nCellX, int32 nCellY, int32 nBrushSize ){
    int32 _nCoordX = nCellX;
    int32 _nCoordY = nCellY;
    int32 _nHalfBrushSize = nBrushSize / 2;
    set<CTerrainBlock*> _vTerrainBlockList;
    vector< float >_vNewHeightList;
    CTerrainBlock* _vTerrainBlock[4];

    CTerrainObject* _pTerrainObject = m_pSceneMgr->GetTerrainObject();
    if (_nHalfBrushSize > 0) {
        float _fMaxDistance = sqrt(Distance(_nCoordX, _nCoordY, _nCoordX + _nHalfBrushSize, _nCoordY + _nHalfBrushSize));
        for (int32 j = _nCoordY - _nHalfBrushSize; j <= _nCoordY + _nHalfBrushSize; j++) {
            for (int32 i = _nCoordX - _nHalfBrushSize; i <= _nCoordX + _nHalfBrushSize; i++) {
                if(i < 0 || j < 0 || i >= _pTerrainObject->m_nCellCountX || j >= _pTerrainObject->m_nCellCountY)
                    continue;
                
                float _fHeight = _pTerrainObject->GetCellHeight( i - 1, j - 1 );
                _fHeight += _pTerrainObject->GetCellHeight( i,     j - 1 );
                _fHeight += _pTerrainObject->GetCellHeight( i + 1, j - 1 );

                _fHeight += _pTerrainObject->GetCellHeight( i - 1, j );
                _fHeight += _pTerrainObject->GetCellHeight( i,     j );
                _fHeight += _pTerrainObject->GetCellHeight( i + 1, j );
                
                _fHeight += _pTerrainObject->GetCellHeight( i - 1, j + 1 );
                _fHeight += _pTerrainObject->GetCellHeight( i,     j + 1 );
                _fHeight += _pTerrainObject->GetCellHeight( i + 1, j + 1 );

                _vNewHeightList.push_back( _fHeight / 9.0f );
            }
        }

        int32 _n = 0;
        for (int32 j = _nCoordY - _nHalfBrushSize; j <= _nCoordY + _nHalfBrushSize; j++) {
            for (int32 i = _nCoordX - _nHalfBrushSize; i <= _nCoordX + _nHalfBrushSize; i++) {
                if(i < 0 || j < 0 || i >= _pTerrainObject->m_nCellCountX || j >= _pTerrainObject->m_nCellCountY)
                    continue;

                int32 _nTerrainBlock = _pTerrainObject->GetCellBlock( i, j, _vTerrainBlock );
                for( int32 n = 0; n < _nTerrainBlock; n ++ ){
                    _vTerrainBlockList.insert( _vTerrainBlock[n] );
                }
                float _fHeight = _pTerrainObject->GetCellHeight( i, j );
                _AddTerrainCellHeightInfo( i, j, _fHeight );
                _pTerrainObject->SetCellHeight( i, j, _vNewHeightList[ _n ++ ]);
            }
        }
        set< CTerrainBlock* >::iterator it = _vTerrainBlockList.begin();
        set< CTerrainBlock* >::iterator it_end = _vTerrainBlockList.end();
        for (; it != it_end; it++) {
            CTerrainBlock* _pTerrainBlock = it.first();
            _pTerrainBlock->UpdateGeometry();
        }
        m_rTerrainActiveBlockHelperObject->UpdateActiveBlock( _nCoordX, _nCoordY, nBrushSize, True );
    }else {

    }
}



